#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <limits.h>
#include <windows.h>
#include <winsvc.h>
#include <winsock2.h>
#include "mongoose.h"
#include "scheme.h"
#include "scheme-private.h"
#include "dynload.h"

#define sleep(n) Sleep(1000 * n)

static const char *standard_reply =	"HTTP/1.1 200 OK\r\n"
					"Content-Type: text/plain\r\n"
					"Connection: close\r\n\r\n";
static int exit_flag;	                /* Program termination flag	*/

static void
signal_handler(int sig_num)
{
#if !defined(_WIN32)
	if (sig_num == SIGCHLD) {
		do {
		} while (waitpid(-1, &sig_num, WNOHANG) > 0);
	} else
#endif /* !_WIN32 */
	{
		exit_flag = sig_num;
	}
}

int init_ts(scheme* sc){
  FILE *fin;
  char *file_name="init.ts";
  int retcode;
  int isfile=1;
  scheme_init(sc);
  //scheme_define(sc,sc->global_env,mk_symbol(sc,"load-extension"),mk_foreign_func(sc, scm_load_ext));
  /*if(access(file_name,0)!=0) {
    char *p=getenv("TSINIT");
    if(p!=0) {
      file_name=p;
    }
  }*/
    fin=fopen(file_name,"r");
    if(fin==0) {
      fprintf(stderr,"Could not open file %s\n",file_name);
    } else {
      scheme_load_file(sc,fin);
			if(isfile) {
				fclose(fin);
			}
    }
  retcode=sc->retcode;
  
  //scheme_deinit(sc);
  return retcode;
}


static void url_callback(struct mg_connection *conn,
		const struct mg_request_info *ri, void *user_data){
			pointer x;
			pointer y;
			pointer p;
			scheme* sc = (scheme*)user_data;
			FILE* s ;//= socket_to_file(conn,"w+");
			
			//struct socket n;
			//n = conn->client.sock;
	//scheme_set_output_port_file(sc, s);
//p = create_port(sc,s,32);
		int n = 0;
		get_socket_fd(conn,&n);
	mg_printf(conn, "%s", standard_reply);
	//send((SOCKET)n,"xxxx%d",6,0);
	s = fdopen((SOCKET)n,"r+");
	fprintf(s,"hello%d");
	y = _cons(sc,mk_string(sc,"method"),mk_string(sc,ri->request_method),0);
	x = _cons(sc,y,sc->NIL,0);
	y = _cons(sc,mk_string(sc,"uri"),mk_string(sc,ri->uri),0);
	x = _cons(sc,y,x,0);
	y = _cons(sc,mk_string(sc,"query-string"),mk_string(sc,(ri->query_string==NULL?"":ri->query_string)),0);
	x = _cons(sc,y,x,0);
	y = _cons(sc,mk_string(sc,"post"),mk_counted_string(sc,(ri->post_data==NULL?"":ri->post_data),ri->post_data_len),0);
	x = _cons(sc,y,x,0); 
	y = _cons(sc,mk_string(sc,"ip"),mk_integer(sc,ri->remote_ip),0);
	x = _cons(sc,y,x,0); 
	p = mk_integer(sc,(long)(&n));
	x = _cons(sc,p,x,0);
	y = scheme_get_defined_var(sc,"call-method");
	scheme_call(sc,y,x);
	//mg_printf(conn, "%d", is_port(p));
}


int
main(int argc, char *argv[])
{
	scheme sc;
	struct mg_context	*ctx;
	pointer port;
	pointer root;

	init_ts(&sc);
	
#ifndef _WIN32
	(void) signal(SIGCHLD, signal_handler);
#endif /* _WIN32 */
	(void) signal(SIGTERM, signal_handler);
	(void) signal(SIGINT, signal_handler);

	if ((ctx = mg_start()) == NULL) {
		(void) printf("%s\n", "Cannot initialize Mongoose context");
		exit(EXIT_FAILURE);
	}
	port = scheme_get_defined_var(&sc,"server-port");
	root = scheme_get_defined_var(&sc,"server-root");

	if (mg_set_option(ctx, "ports", (port == sc.NIL)?"80":string_value(port)) != 1)
		exit(EXIT_FAILURE);
  if (mg_set_option(ctx, "root", (root == sc.NIL)?".":string_value(root)) != 1)
		exit(EXIT_FAILURE);
	mg_set_uri_callback(ctx, "/*", &url_callback, &sc);
	printf("Mongoose %s started on port(s) [%s], serving directory [%s]\n",
	    mg_version(),
	    mg_get_option(ctx, "ports"),
	    mg_get_option(ctx, "root"));

	fflush(stdout);
	while (exit_flag == 0)
		sleep(1);

	(void) printf("Exiting on signal %d, "
	    "waiting for all threads to finish...", exit_flag);
	fflush(stdout);
	scheme_deinit(&sc);
	mg_stop(ctx);
	(void) printf("%s", " done.\n");

	return (EXIT_SUCCESS);
}
